﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Peninsula.Utility.Extensions
{
    public static class EnumerableExtensions
    {
        public static string JoinToString<T>(this IEnumerable<T> enumlist, string split = ",")
        {
            string result = string.Empty;
            enumlist.ForEach(e => 
            {
                result += e.ToString() + split;
            });
            return result.Substring(0, result.Length > 0 ? (result.Length - 1) : 0);
        }

        /// <summary>
        /// 判断集合中是否有元素，集合为空不会异常
        /// </summary>
        public static bool IsNotEmpty<T>(this IEnumerable<T> enumlist)
        {
            return enumlist != null && enumlist.Count() > 0;
        }

        /// <summary>
        /// 判断集合中是否有元素，集合为空不会异常
        /// </summary>
        public static bool IsEmpty<T>(this IEnumerable<T> enumlist)
        {
            return enumlist == null || enumlist.Count() == 0;
        }

        /// <summary>
        /// 分页
        /// </summary>
        public static IEnumerable<T> Paging<T>(this IEnumerable<T> enumlist, int pageIndex, int pageSize, bool paging = true)
        {
            if (!paging)
            {
                return enumlist;
            }

            int startIndex = pageSize * (pageIndex - 1);

            if (startIndex <= 0)
            {
                startIndex = 0;
            }

            return enumlist.Skip(startIndex).Take(pageSize);
        }

        /// <summary>
        /// 分页，返回总页数
        /// </summary>
        public static IEnumerable<T> Paging<T>(this IEnumerable<T> enumlist, int pageIndex, int pageSize, out int totalPage)
        {
            totalPage = Convert.ToInt32(Math.Ceiling((decimal)enumlist.Count() / pageSize));
            return Paging(enumlist, pageIndex, pageSize);
        }



        public static void ForEach<T>(this IEnumerable<T> collection, Action<T> action)
        {
            if (collection == null)
                return;
            foreach (T ele in collection)
                action(ele);
        }

        public static void ForEach<T>(this IEnumerable<T> collection, Action<T, int> action)
        {
            if (collection == null)
                return;
            int idx = 0;
            foreach (T ele in collection)
                action(ele, idx++);
        }

        public static void ForEach<T>(this IEnumerable<T> collection, Func<T, bool> action)
        {
            if (collection == null)
                return;
            foreach (T ele in collection)
            {
                bool result = action(ele);
                if (!result)
                    return;
            }
        }

        public static void ForEach<T>(this IEnumerable<T> collection, Func<T, int, bool> action)
        {
            if (collection == null)
                return;
            int idx = 0;
            foreach (T ele in collection)
            {
                bool result = action(ele, idx++);
                if (!result)
                    return;
            }
        }

        public static R ForEach<T, R>(this IEnumerable<T> collection, Func<T, R> action)
        {
            return ForEach<T, R>(collection, action, o => o != null);
        }

        public static R ForEach<T, R>(this IEnumerable<T> collection, Func<T, R> action, Predicate<R> breakNextProvicerAction)
        {
            if (collection == null)
                return default(R);
            foreach (T ele in collection)
            {
                R result = action(ele);
                if (breakNextProvicerAction(result))
                    return result;
            }
            return default(R);
        }

        public static int ElementIndex<T>(this IEnumerable<T> collection, T obj)
        {
            if (collection == null)
                return -1;
            int idx = -1;
            foreach (T ele in collection)
            {
                idx++;
                if (ele.Equals(obj))
                    return idx;
            }
            return -1;
        }

        public static int ElementIndex<T>(this IEnumerable<T> collection, Predicate<T> predicate)
        {
            if (collection == null)
                return -1;
            int idx = -1;
            foreach (T ele in collection)
            {
                idx++;
                if (predicate(ele))
                    return idx;
            }
            return -1;
        }

        public static IEnumerable<U> Cast<T, U>(this IEnumerable<T> collection, Func<T, U> converter)
        {
            if (collection == null)
                return Enumerable.Empty<U>();
            List<U> list = new List<U>();
            foreach (T obj in collection)
                list.Add(converter(obj));
            return list;
        }

        public static IEnumerable<U> ConcatProperty<T, U>(this IEnumerable<T> collection, Func<T, IEnumerable<U>> getter)
        {
            if (collection == null)
                return Enumerable.Empty<U>();
            List<U> list = new List<U>();
            foreach (T obj in collection)
            {
                list.AddRange(getter(obj));
            }
            return list;
        }

        public static IList<T> AsList<T>(this IEnumerable<T> collection)
        {
            List<T> list = new List<T>();
            if (collection != null)
                list.AddRange(collection);
            return list;
        }

        public static void Merge<T>(this IList<T> collection, IEnumerable<T> targets, Func<IEnumerable<T>, T, bool> exists)
        {
            if (collection == null)
                return;
            foreach (T obj in targets)
                if (exists(collection, obj) == false)
                    collection.Add(obj);
        }
    }
}
